package com.sfx.concurrent.demo.concurrent.AtomicTest.ABA;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.atomic.AtomicStampedReference;

@Slf4j(topic = "c.SolveCASABAIssue")
public class SolveCASABAIssue {
    private static AtomicStampedReference<String> ref =
            new AtomicStampedReference<>("A",1);
    public static void main(String[] args) throws InterruptedException {
        /**
         * 使用AtomicReference CAS操作并不能知道值已经被其他线程修改过了 例如 ABA问题
         * 要想解决就要引入版本号 AtomicStampedReference
         */
        //使用CAS将其A改变为C
        String prev = ref.getReference();
        //获取到版本号
        int stamped = ref.getStamp();
        log.debug("版本号 : {}",ref.getStamp());
        other();
        Thread.sleep(1000);
        log.debug("A->C : {}",ref.compareAndSet(prev,
                "C",stamped,stamped+1));
    }

    public static void other() throws InterruptedException {
        new Thread(()->{
            int stamped = ref.getStamp();
            log.debug("A->B{}",ref.compareAndSet(ref.getReference(),
                    "B",stamped,stamped+1));
        },"t1").start();
        Thread.sleep(1000);
        new Thread(()->{
            int stamped = ref.getStamp();
            log.debug("B->A{}",ref.compareAndSet(ref.getReference(),
                    "A",stamped,stamped+1));
        },"t2").start();
    }
}